package org.luckyjourney.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.*;
import cn.hutool.json.JSONNull;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.luckyjourney.constant.RedisConstant;
import org.luckyjourney.controller.wx.WechatPayConfig;
import org.luckyjourney.entity.Captcha;
import org.luckyjourney.entity.consultants.TalConsultants;
import org.luckyjourney.entity.dto.UserWXLoginDTO;
import org.luckyjourney.entity.regularusers.RegularUsers;
import org.luckyjourney.entity.user.AuthenticationDTO;
import org.luckyjourney.entity.user.User;
import org.luckyjourney.entity.user.dto.UserDTO;
import org.luckyjourney.entity.vo.FindPWVO;
import org.luckyjourney.entity.vo.RegisterVO;
import org.luckyjourney.exception.BaseException;
import org.luckyjourney.holder.UserHolder;
import org.luckyjourney.mapper.regularusers.RegularUsersMapper;
import org.luckyjourney.mapper.user.UserMapper;
import org.luckyjourney.properties.WeChatProperties;
import org.luckyjourney.service.CaptchaService;
import org.luckyjourney.service.LoginService;
import org.luckyjourney.service.regularusers.RegularUsersService;
import org.luckyjourney.service.user.UserService;
import org.luckyjourney.util.HttpClientUtil;
import org.luckyjourney.util.HttpRequestUtil;
import org.luckyjourney.util.MD5Utils;
import org.luckyjourney.util.RedisCacheUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.test.WechatMinAppLoginVO;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:
 * @Author: Xhy
 * @CreateTime: 2023-11-04 12:38
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private UserService userService;

    @Autowired
    private CaptchaService captchaService;

    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;//防止乱码
    @Autowired
    UserMapper userMapper;
    @Autowired
    WechatPayConfig wechatPayConfig;
    public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";

    @Override
    public User login(User user) {
        final String password = user.getPassword();
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        user = userService.getOne(wrapper.eq(User::getPhone, user.getPhone()));

        if (ObjectUtils.isEmpty(user)) {
            throw new BaseException("没有该账号");
        }
        User user1 = new User();
        user1.setOpenid(user.getOpenid());
        userMapper.updateById(user1);
        if (!MD5Utils.GetMD5Code(password).equals(user.getPassword())) {
            throw new BaseException("密码不一致");
        }

        return user;
    }

    @Override
    public Boolean checkCode(String email, Integer code) {
        if (ObjectUtils.isEmpty(email) || ObjectUtils.isEmpty(code)) {
            throw new BaseException("参数为空");
        }
        final Object o = redisCacheUtil.get(RedisConstant.EMAIL_CODE + email);

        if (!code.toString().equals(o)) {
            throw new BaseException("验证码不正确");

        }
        return true;
    }

    @Override
    public void captcha(String uuId, HttpServletResponse response) throws IOException {
        if (ObjectUtils.isEmpty(uuId)) {
            throw new IllegalArgumentException("uuid不能为空");
        }
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        BufferedImage image = captchaService.getCaptcha(uuId);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
        IOUtils.closeQuietly(out);
    }

    @Override
    public Boolean getCode(Captcha captcha) throws Exception {

        return captchaService.validate(captcha);
    }

    @Override
    public Boolean register(RegisterVO registerVO) throws Exception {
        // 注册成功后删除图形验证码
        if (userService.register(registerVO)) {

            return true;
        }
        return false;
    }

    @Override
    public Boolean findPassword(FindPWVO findPWVO) {
        final Boolean b = userService.findPassword(findPWVO);
        return b;
    }

    @Override
    public User PhoneLogin(UserDTO userDTO) throws Exception {
        String codeInSession = redisTemplate.opsForValue().get(userDTO.getPhone());
        if (ObjectUtil.isEmpty(codeInSession)) {
            throw new BaseException("验证码已失效");
        }
        String phone = userDTO.getPhone();
        if (ObjectUtil.isNotEmpty(codeInSession) && codeInSession.equals(userDTO.getCode())) {

            User consultantss = userMapper.selectId(phone);
            if (ObjectUtil.isNotEmpty(consultantss)) {

                if (consultantss.getPhone().equals(phone)) {
                    return consultantss;
                }
            } else {
                User user = getUser(userDTO, phone);
                if (user != null) {
                    return user;
                }
            }
        } else {
            throw new BaseException("验证码错误");
        }
        return null;
    }

    /**
     * 微信小程序登录
     *
     * @param userWXLoginDTO
     * @return
     */
    @Override
    public User wxLogin(UserWXLoginDTO userWXLoginDTO) {
        String openid = getString(userWXLoginDTO);
        if(ObjectUtil.isEmpty(openid)){
            throw new BaseException("登录失败");
        }
        User user=userMapper.selectOpenId(openid);
        if(ObjectUtil.isEmpty(user)){
            User user1 = new User();
            user1.setOpenid(openid);
            return user1;
        }
        return user;
    }

    /**
     * 微信小程序手机号登录
     * @param userDTO
     * @return
     */
    @Override
    public String WXPhone(UserDTO userDTO) throws Exception {
        String opencode = userDTO.getOpencode();
        String phone = getString(opencode);

        return phone;
    }

    @Override
    public User WXPhoneLogin(UserDTO userDTO) throws Exception {
        String phone = userDTO.getPhone();
        String openid = userDTO.getOpenid();
        if(ObjectUtil.isNotEmpty(phone)){
            User consultantss = userMapper.selectId(phone);
            if (ObjectUtil.isNotEmpty(consultantss)) {
                //更新openid，手机号存在
                User user1 = new User();
                user1.setId(consultantss.getId());
                user1.setOpenid(userDTO.getOpenid());
                userMapper.updateById(user1);
                if (consultantss.getPhone().equals(phone)) {
                    return consultantss;
                }
            }else {
                User user = getUser(userDTO, phone);
                if (user != null) {
                    return user;
                }
            }
        }
        if(ObjectUtil.isNotEmpty(openid)){
            User userOpenId=userMapper.selectOpenId(openid);
            if (ObjectUtil.isNotEmpty(userOpenId)) {
                if (userOpenId.getOpenid().equals(openid)) {
                    return userOpenId;
                }
            }
        }

        return null;
    }

    private User getUser(UserDTO userDTO, String phone) throws Exception {
        //不存在就去注册
        RegisterVO registerVO = new RegisterVO();
        registerVO.setPhone(phone);
        registerVO.setPassword("123456");
        registerVO.setCode(userDTO.getCode());
        registerVO.setModuleId(userDTO.getModuleId());
        registerVO.setOpenid(userDTO.getOpenid());
        userService.register(registerVO);
        //先去注册
        User user = userMapper.selectId(phone);
        if (user.getPhone().equals(phone)) {
            return user;
        }
        return null;
    }

    private String getString(String opencode) {
        String authorizer_appid = wechatPayConfig.getAppId();
        String secret = wechatPayConfig.getAppSecret();
        // 调用接口必要的参数
        Map<String, Object> data = new HashMap<>();
        // appid、secret定义在配置文件中，注入到项目里
        data.put("appid", authorizer_appid);
        data.put("secret", secret);
        data.put("grant_type", "client_credential");
        System.out.println("data = " + data);
        String response1 = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token", data);
        System.out.println("response1 = " + response1);
        // 将返回值封装成实体类
        WechatMinAppLoginVO weChatMinAppLoginVo = JSONUtil.toBean(response1, WechatMinAppLoginVO.class);
        String access_token = weChatMinAppLoginVo.getAccess_token();
        System.out.println("access_token = " + access_token);
        // 调用接口必要的参数
        Map<String, Object> data1 = new HashMap<>();
        data1.put("code", opencode);
        String paramJson = JSONUtil.toJsonStr(data1);
        System.out.println("请求微信手机号====="+paramJson);
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+access_token;
        System.out.println("url = " + url);
        //这里要特别注意，调用二维码接口返回的是二进制，所以返回值必须为Byte类型，返回String类型就会变成乱码
        String response = HttpRequest
                .post(url)
                .header("Content-Type", "application/json")
                .body(paramJson)
                .execute()
                .body();
        System.out.println("response = " + response);
        WechatMinAppLoginVO wechatMinAppLoginVO = JSONUtil.toBean(response, WechatMinAppLoginVO.class);
        cn.hutool.json.JSONObject entries = JSONUtil.parseObj(wechatMinAppLoginVO.getPhone_info());
        String phone = entries.getStr("phoneNumber");
        System.out.println("获取到当前用户的手机号："+phone);
        return phone;
    }

    private String getString(UserWXLoginDTO userWXLoginDTO) {
        Map<String, String> map=new HashMap<>();

        map.put("appid",wechatPayConfig.getAppId());
        map.put("secret",wechatPayConfig.getAppSecret());
        map.put("js_code", userWXLoginDTO.getCode());
        map.put("grant_type","authorization_code");
        String json = HttpClientUtil.doGet(WX_LOGIN, map);

        JSONObject jsonObject = JSON.parseObject(json);

        String openid = jsonObject.getString("openid");
        return openid;
    }

}
